﻿using System;
using System.Diagnostics;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using HostsManager.Model;

namespace HostsManager.Services
{
    public class HostsService
    {
        public static Hosts LoadHostsFromFile(String fullPath)
        {
            if (!File.Exists(fullPath))
                throw new FileNotFoundException("File not found", fullPath);

            FileStream stream = new FileStream(fullPath, FileMode.Open);
            StreamReader reader = new StreamReader(stream);

            Hosts hosts = new Hosts();
            Configuration currentConfiguration = hosts.DefaultConfiguration;

            String currentSectionName = String.Empty;
            String currentConfigurationName = String.Empty;

            bool mustAddLine;

            String line = reader.ReadLine();
            while (line != null)
            {
                line = StringUtil.CompactSpaces(line).Trim();
                mustAddLine = true;

                if (line.StartsWith("#!"))
                {
                    String[] tokens = line.SplitPreservingQuotes(' ').ToArray<String>();

                    if (tokens.Length >= 4)
                    {
                        switch (tokens[1])
                        {
                            case "section":
                                currentSectionName = tokens[2];
                                currentConfigurationName = String.Empty;
                                Section section = new Section(currentSectionName, tokens[3].ToLower() == "on");
                                hosts.AddSection(section);
                                currentConfiguration = hosts.DefaultConfiguration;
                                mustAddLine = false;
                                break;

                            case "configuration":
                                Debug.Assert(currentSectionName != String.Empty);

                                currentConfigurationName = tokens[2];
                                hosts.AddConfiguration(currentSectionName, currentConfigurationName, tokens[3]);

                                currentConfiguration = hosts.Sections[currentSectionName].GetConfiguration(currentConfigurationName);
                                Debug.Assert(currentConfiguration != null);
                                mustAddLine = false;
                                break;
                        }
                    }
                }

                if (mustAddLine)
                    currentConfiguration.AddLine(line);

                line = reader.ReadLine();
            }

            reader.Close();

            return hosts;
        }

        public static void SaveHostsToFile(Hosts hosts, string fullPath)
        {
            // TODO:
            // FileUtils.Backup(fullPath);

            if (hosts == null)
                throw new ArgumentNullException(strings.NoHostsToSave);

            FileStream stream = new FileStream(fullPath, FileMode.Create);
            StreamWriter writer = new StreamWriter(stream);

            foreach (Section s in hosts.Sections.Values)
            {
                if (s != hosts.DefaultSection)
                {
                    string header = Environment.NewLine + "#! section \"" + s.Name + "\" " + (s.Enabled ? "on" : "off") + " ";
                    writer.WriteLine(header.PadRight(80, '#'));
                }

                foreach (Configuration c in s.Configurations)
                {
                    if (c != hosts.DefaultConfiguration)
                        writer.WriteLine(Environment.NewLine + "#! configuration \"" + c.Name + "\" " + (c.Enabled ? "on" : "off"));

                    string prefix = (c.Enabled && s.Enabled ? "" : "#! ");

                    StringReader reader = new StringReader(c.Content);

                    string line;
                    while ((line = reader.ReadLine()) != null)
                    {
                        if (line != string.Empty && prefix != string.Empty && !line.StartsWith("#"))
                            line = prefix + line;

                        writer.WriteLine(line);
                    }
                }
            }

            // Make all other appended entries belong to global section/configuration
            writer.WriteLine(Environment.NewLine + "#! section \"" + hosts.DefaultSection.Name + "\" " + (hosts.DefaultSection.Enabled ? "on" : "off") + " ");
            writer.WriteLine(Environment.NewLine + "#! configuration \"" + hosts.DefaultConfiguration.Name + "\" " + (hosts.DefaultConfiguration.Enabled ? "on" : "off"));

            writer.Flush();
            writer.Close();
        }
    }
}
